package com.lfz.search.service;

import com.lfz.search.vo.Page;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.function.Consumer;

@Service
public class SearchService {

	@Autowired
	private TransportClient transportClient;

	private static final Set<String> SEARCH_TYPES = new HashSet<>();

	static {
		SEARCH_TYPES.add("job_item");
	}

	public Page search(Page page) {

		List<Map<String, Object>> list = new ArrayList<>();
		String searchType = page.getSearchType();
		if (SEARCH_TYPES.contains(searchType)) {

			BoolQueryBuilder mustQuery = QueryBuilders.boolQuery();

			// 关键字匹配
            if (!StringUtils.isEmpty(page.getQ())) {
                MultiMatchQueryBuilder query = QueryBuilders.multiMatchQuery(page.getQ(), "jobName", "compName",
                        "compIndustry", "compStage", "eduLevel", "workingExp");
                mustQuery.must(query);
            }


			// 发货位置字段精确匹配
			List<Integer> locs = page.getLoc();
			if (locs.size() != 0) {
				mustQuery.must(QueryBuilders.termsQuery("loc", locs));
			}

			// 分类精确匹配
			List<Integer> cats = page.getCat();
			if (cats.size() != 0) {
				mustQuery.must(QueryBuilders.termsQuery("cat", cats));
			}

			// 标签精确匹配
			List<Integer> tags = page.getTag();
			if (tags.size() != 0) {
				mustQuery.must(QueryBuilders.termsQuery("tag", tags));
			}

			// 薪资范围
			List<Integer> reservePrice = page.getReservePrice();
			if (reservePrice.size() == 2) {
                RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("minSalary")
						.from(page.getReservePrice().get(0)).to(page.getReservePrice().get(1))
                        .includeLower(true).includeUpper(true);
                mustQuery.should(rangeQueryBuilder);
                rangeQueryBuilder = QueryBuilders.rangeQuery("maxSalary")
                        .from(page.getReservePrice().get(0)).to(page.getReservePrice().get(1))
                        .includeLower(true).includeUpper(true);
                mustQuery.should(rangeQueryBuilder);
			}

			SearchRequestBuilder prepareSearch = transportClient.prepareSearch("job_item");

			// 排序
			List<String> sorts = page.getSort();
			// 如果发布时间不在排序字段中，添加按发布时间倒序排序
            if (!(sorts.contains("releaseTime-desc") || sorts.contains("releaseTime-asc"))) {
                sorts.add("releaseTime-desc");
            }
            // 最后添加按jobId倒序排序
            sorts.add("jobId-desc");
			for (String sort : sorts) {
				String[] fieldAndRule = sort.split("-");
				if (fieldAndRule.length == 2) {
					FieldSortBuilder fieldSort = SortBuilders.fieldSort(fieldAndRule[0]);
					if ("asc".equals(fieldAndRule[1])) {
						fieldSort.order(SortOrder.ASC);
						prepareSearch.addSort(fieldSort);
					} else if ("desc".equals(fieldAndRule[1])) {
						fieldSort.order(SortOrder.DESC);
						prepareSearch.addSort(fieldSort);
					}
				}
			}

			// 查询
			SearchHits searchHits = prepareSearch.setFrom(page.getBegin()).setSize(page.getRows())
					.setQuery(mustQuery).get().getHits();

			// 获取总记录数
			long totalHits = searchHits.getTotalHits();

			// 获取记录
			searchHits.forEach(new Consumer<SearchHit>() {

				@Override
				public void accept(SearchHit t) {
					list.add(t.getSource());
				}

			});

			page.setTotal(totalHits);
			page.setData(list);

		}
		return page;
	}

}
